package org.JWCB.friend.service.question;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.JWCB.common.core.domain.vo.TableDataInfo;
import org.JWCB.common.core.enums.ResultCode;
import org.JWCB.common.core.exception.ServiceException;
import org.JWCB.friend.aspect.CheckUserStatus;
import org.JWCB.friend.domain.question.dto.QuestionQueryDto;
import org.JWCB.friend.domain.question.entity.Question;
import org.JWCB.friend.domain.question.es.QuestionES;
import org.JWCB.friend.domain.question.vo.*;
import org.JWCB.friend.elasticsearch.QuestionRepository;
import org.JWCB.friend.manager.QuestionCacheManager;
import org.JWCB.friend.mapper.question.QuestionMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class QuestionService {

    private static final Logger log = LoggerFactory.getLogger(QuestionService.class);
    @Autowired
    private QuestionRepository questionRepository;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionCacheManager questionCacheManager;

    @Value("${redis.noneValueExpMin:60}")
    private long noneValExpMin;


    @Autowired
    private QuestionTagService questionTagService;

    /**
     * 获取题目列表
     * 
     * @param queryDto 查询参数
     */
    public TableDataInfo list(QuestionQueryDto queryDto) {
        long total = questionRepository.count();
        if (total <= 0) {
            // 刷新es缓存
            refreshES();
        }
        Pageable pageable = PageRequest.of(queryDto.getPageNum() - 1, queryDto.getPageSize(),
                Sort.by(Sort.Direction.DESC, "createTime"));
        Integer difficulty = queryDto.getDifficulty();
        String keyword = queryDto.getKeyword();
        Page<QuestionES> questionESList;
        if (difficulty == null && StrUtil.isEmpty(keyword)) {
            questionESList = questionRepository.findAll(pageable);
        } else if (StrUtil.isEmpty(keyword)) {
            questionESList = questionRepository.findQuestionByDifficulty(difficulty, pageable);
        } else if (difficulty == null) {
            questionESList = questionRepository.findByTitleOrContent(keyword, keyword, pageable);
        } else {
            questionESList = questionRepository.findByTitleOrContentAndDifficulty(keyword, keyword, difficulty,
                    pageable);
        }
        long totalElements = questionESList.getTotalElements();
        if (totalElements <= 0) {
            return TableDataInfo.empty();
        }
        List<QuestionListItemVo> questionListItemVos = BeanUtil.copyToList(questionESList.getContent(),
                QuestionListItemVo.class);
        return TableDataInfo.success(questionListItemVos, totalElements);
    }

    /**
     * 刷新es
     */
    private void refreshES() {
        List<Question> questionList = questionMapper.selectList(new LambdaQueryWrapper<Question>()
                .orderByDesc(Question::getCreateTime, Question::getQuestionId));
        log.info("插入es数据idList{}", questionList.stream().map(Question::getQuestionId).toList());
        if (CollectionUtil.isEmpty(questionList)) {
            return;
        }
        List<QuestionES> questionESList = BeanUtil.copyToList(questionList, QuestionES.class);
        for (QuestionES questionES : questionESList) {
            List<QuestionTagVo> questionAllTag = questionTagService.getQuestionAllTag(questionES.getQuestionId());
            questionES.setQuestionTagList(questionAllTag);
        }
        questionRepository.saveAll(questionESList);
    }

    /**
     * 获取题目详情
     */
    public QuestionDetailVo detail(Long questionId) {
        if (questionId == null) {
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        QuestionES questionES = questionRepository.findById(questionId).orElse(null);
        QuestionDetailVo questionDetailVo = new QuestionDetailVo();
        if (questionES != null) {
            BeanUtil.copyProperties(questionES, questionDetailVo);
            questionDetailVo.setQuestionCaseList(JSON.parseArray(questionES.getQuestionCase(), QuestionCase.class));
            return questionDetailVo;
        }
        Question question = questionMapper.selectById(questionId);
        if (question == null) {
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        refreshES();
        BeanUtil.copyProperties(question, questionDetailVo);
        questionDetailVo.setQuestionCaseList(JSON.parseArray(question.getQuestionCase(), QuestionCase.class));
        List<QuestionTagVo> questionAllTag = questionTagService.getQuestionAllTag(questionDetailVo.getQuestionId());
        questionDetailVo.setQuestionTagList(questionAllTag);
        return questionDetailVo;
    }

    /**
     * 下一道题
     */
    public String nextQuestion(Long questionId) {
        long listSize = questionCacheManager.getListSize();
        if (listSize <= 0) {
            questionCacheManager.refreshCache();
        }
        return questionCacheManager.nextQuestion(questionId).toString();
    }

    /**
     * 上一道题
     */
    public String prevQuestion(Long questionId) {
        long listSize = questionCacheManager.getListSize();
        if (listSize <= 0) {
            questionCacheManager.refreshCache();
        }
        return questionCacheManager.preQuestion(questionId).toString();
    }

    /**
     * 获取热榜数据
     */
    public List<HotQuestionListVo> hotQuestion() {
        List<HotQuestionListVo> hotQuestionList = questionCacheManager.getHotQuestionList();
        if(CollectionUtil.isEmpty(hotQuestionList)) {
            return new ArrayList<>();
        }
        return hotQuestionList;
    }
}
